﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Expect.Core.Interfaces;
using Expect.Core.Html;

namespace Expect.Core.IO
{
    /*
    /// <summary>
    /// Reader implementation for Html format
    /// </summary>
    public class HtmlSpecificationReader : HtmlSpecification, ISpecificationReader
    {
        /// <summary>
        /// Read a specification from the provided stream
        /// </summary>
        /// <param name="inputname">name of the input, for example, file name without extension</param>
        /// <param name="stream">the stream providing the specification</param>
        /// <returns>spec definition</returns>
        public SpecificationDefinition ReadSpecification(string inputname, Stream stream)
        {
            HtmlDocument htmlDoc = new HtmlDocument();
            htmlDoc.Load(stream);
            return LoadDocument(htmlDoc);
        }

        /// <summary>
        /// Read a specification from the provided string
        /// </summary>
        /// <param name="inputname">name of the input, for example, file name without extension</param>
        /// <param name="s">the string representation of the specification</param>
        /// <returns>spec definition</returns>
        public SpecificationDefinition ReadSpecification(string inputname, string s)
        {
            HtmlDocument htmlDoc = new HtmlDocument();
            htmlDoc.LoadHtml(s);
            return LoadDocument(htmlDoc);
        }

        private SpecificationDefinition LoadDocument(HtmlDocument htmlDoc)
        {
            SpecificationDefinition spec = new SpecificationDefinition();
            spec.Source = htmlDoc;
            Parse(htmlDoc.DocumentNode, spec);
            return spec;
        }

        private void Parse(HtmlNode node, SpecificationDefinition spec)
        {
            if (string.Compare(node.Name, "table", true) == 0)
            {
                ParseTableNode(node, spec);
            }
            else if (IsAFixtureNode(node))
            {
                ParseFixture(node,spec, null);
            }
            else
            {
                foreach(var childnode in node.ChildNodes)
                {
                    Parse(childnode, spec);
                }
            }
        }

        private bool HasCssClassAttribute(HtmlNode node, string cssclass)
        {
            HtmlAttribute attr = node.Attributes["class"];
            if (attr != null)
            {
                return attr.Value == cssclass;
            }

            return false;
        }

        

        private void ParseTableNode(HtmlNode node, SpecificationDefinition spec)
        {
            FixtureDefinition fixture = new FixtureDefinition(spec);
            fixture.Source = node;
            foreach (var childnode in node.ChildNodes)
            {
                if (string.Compare(childnode.Name, "tr", true) == 0)
                {                    
                    ParseTableRow(childnode, spec, fixture);                    
                }
            }
            spec.Add(fixture);
        }

        private void ParseTableRow(HtmlNode node, SpecificationDefinition spec, FixtureDefinition fixture)
        {
            FixtureRow row = new FixtureRow();
            row.Source = node;
            foreach(var cellnode in node.ChildNodes)
            {
                if (string.Compare(cellnode.Name, "td", true) == 0)
                {
                    var cell = row.AddCell(cellnode.InnerText.Trim());
                    cell.Source = cellnode;
                }
            }
            fixture.Add(row);
        }

        private bool IsAFixtureNode(HtmlNode node)
        {
            return HasCssClassAttribute(node, "fixture");
        }

        private bool IsARowNode(HtmlNode node)
        {
            return HasCssClassAttribute(node, "row");
        }

        private bool IsACellNode(HtmlNode node)
        {
            return HasCssClassAttribute(node, "cell");
        }

        private void ParseFixture(HtmlNode node, SpecificationDefinition spec, FixtureDefinition fixture)
        {
            if (fixture == null)
            {
                fixture = spec.AddFixture();
                fixture.Source = node;
            }

            foreach(var childnode in node.ChildNodes)
            {
                if (IsARowNode(childnode))
                {
                    ParseFixtureRow(childnode,spec, fixture, null);
                }
                else
                {
                    ParseFixture(childnode, spec, fixture);
                }
            }
        }

        private void ParseFixtureRow(HtmlNode node, SpecificationDefinition spec, FixtureDefinition fixture, FixtureRow row)
        {
            if (row == null)
            {
                row = new FixtureRow();
                fixture.Add(row);
                row.Source = node;
            }

            foreach (var cellnode in node.ChildNodes)
            {
                if (IsACellNode(cellnode))
                {
                    var cell = row.AddCell(cellnode.InnerText);
                    cell.Source = cellnode;
                }
                else
                {
                    ParseFixtureRow(cellnode, spec, fixture, row);
                }
            }
        }
    }*/
}
